define([ 'require', 'game/objects/hex', 'game/math', 'game/canvas', 'game/consts' ], function(require, hex, math, canvas, consts) {
    return function() {
        var neighbors = new Array([ +1, 0 ], [ +1, -1 ], [ 0, -1 ], [ -1, 0 ], [ -1, +1 ], [ 0, +1 ]);
        var plane = {

            hexes: [],

            __hexmap: {},

            __hexmap_n: {},

            hex: function(grid_x, grid_y, type) {
                this.hexes.push(hex(grid_x, grid_y, type));
                this.recompute();
            },

            recompute: function() {
                var hexes = this.hexes;
                var hexmap = this.__hexmap = {};
                var hexmap_n = this.__hexmap_n = {};
                for (var i = 0; i < hexes.length; ++i) {
                    var h = hexes[i];
                    var hc = {
                        x: h.grid_x,
                        y: h.grid_y
                    };
                    var _ymap = hexmap[hc.x] || (hexmap[hc.x] = {});
                    _ymap[hc.y] = h;
                    for (var j = 0; j < neighbors.length; ++j) {
                        var ndc = neighbors[j];
                        var nc = {
                            x: hc.x + ndc[0],
                            y: hc.y + ndc[1]
                        };
                        var _ymap_n = hexmap_n[nc.x] || (hexmap_n[nc.x] = {});
                        if (!_ymap_n[nc.y]) {
                            _ymap_n[nc.y] = hex(nc.x, nc.y, 'unknown');
                        }
                    }
                }
            },

            draw: function() {
                this.__draw_hexmap(this.__hexmap_n);
                this.__draw_hexmap(this.__hexmap);
            },

            __draw_hexmap: function(hexmap) {
                for ( var x in hexmap) {
                    var _ymap = hexmap[x];
                    for ( var y in _ymap) {
                        var hex = _ymap[y];
                        hex.draw();
                    }
                }
            },

            gethex: function() {
                var args = new Array();
                Array.prototype.push.apply(args, arguments);
                var coords = args.shift();
                if (typeof coords != 'object') {
                    coords = {
                        x: coords,
                        y: args.shift()
                    };
                }
                var h = this.__gethex_from_hexmap(this.__hexmap, coords);
                if (!h) {
                    h = this.__gethex_from_hexmap(this.__hexmap_n, coords);
                }
                return h;
            },

            __gethex_from_hexmap: function(hexmap, coords) {
                return hexmap ? (hexmap[coords.x] ? hexmap[coords.x][coords.y] : null) : null;
            }

        };
        return plane;
    };
});
